package com.example.job07.config;

import com.baomidou.mybatisplus.extension.spring.MybatisSqlSessionFactoryBean;
import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

/**
 * Created by chenmohan on 2020/01/06
 *
 * @description 数据源以及sqlsessionFactory配置
 */
@Slf4j
@Configuration
public class MultiDataSourceConfig {

    @Autowired
    DataSourcePropertiesConfig dsConfig;

    //目标数据源
    private Map<Object, Object> targetDataSources = new HashMap<>();

    //默认数据源
    private Object defaultTargetDataSource;

    @Bean("sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean(@Autowired @Qualifier("dynamicDataSource") DynamicDatasource dynamicDataSource) throws Exception {
        MybatisSqlSessionFactoryBean sqlSessionFactoryBean = new MybatisSqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dynamicDataSource);
        PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();        sqlSessionFactoryBean.setMapperLocations(resolver.getResources("classpath*:mapper/*Mapper.xml"));
        return sqlSessionFactoryBean.getObject();
    }

    @Bean("dynamicDataSource")
    public DynamicDatasource init() {
        List<DataSourcePropertiesConfig.Config> configs = dsConfig.getDs();
        configs.forEach(e -> log.info("读取到的数据源配置有: {}", e));

        DynamicDatasource dynamicDatasource = new DynamicDatasource();
        for (DataSourcePropertiesConfig.Config config : configs) {
            //检查数据库连接前缀是否正确
            if (!config.getUrl().startsWith("jdbc:mysql://")) {
                log.warn("有数据源配置参数错误,该配置跳过,config:{}", config);
                continue;
            }
            DataSource dataSource = buildDataSource(config);
            Object ds = targetDataSources.get(config.getServerId());
            if (ds != null) {
                throw new RuntimeException("spring.datasource.ck.serverId已存在,请检查application.properties");
            }
            targetDataSources.put(config.getServerId(), dataSource);
        }

        //设置默认数据源
        dynamicDatasource.setTargetDataSources(targetDataSources);
        dynamicDatasource.setTargetDataSourceMap(targetDataSources);

        defaultTargetDataSource = targetDataSources.get(configs.get(0).getServerId());
        dynamicDatasource.setDefaultTargetDataSource(defaultTargetDataSource);

        DataSourceContext.setRouteKey(configs.get(0).getServerId());
        return dynamicDatasource;
    }

    private DataSource buildDataSource(DataSourcePropertiesConfig.Config config) {
        Properties properties = new Properties();
        properties.setProperty("driverClassName", "com.mysql.jdbc.Driver");
        properties.setProperty("jdbcUrl", config.getUrl());
        properties.setProperty("username", config.getUserName());
        properties.setProperty("password", config.getPassword());

        HikariConfig hikariConfig = new HikariConfig(properties);
       HikariDataSource dataSource = new com.zaxxer.hikari.HikariDataSource(hikariConfig);

        log.info("加载数据源--------------->{}", config);
        return dataSource;
    }

}
